{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "---\n",
    "title: Functions\n",
    "sidebar_position: 2\n",
    "description: Introduction to Mojo `fn` and `def` functions.\n",
    "---"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As mentioned in [Language basics](/mojo/manual/basics), Mojo supports two\n",
    "types of functions: `def` and `fn` functions. You can use either declaration\n",
    "with any function, including the `main()` function, but they have different\n",
    "default behaviors, as described on this page.\n",
    "\n",
    "We believe both `def` and `fn` have good use cases and don't consider either to\n",
    "be better than the other. Deciding which to use is a matter of personal taste as\n",
    "to which style best fits a given task.\n",
    "\n",
    "We believe Mojo's flexibility in this regard is a superpower that allows you to\n",
    "write code in the manner that's best for your project.\n",
    "\n",
    ":::note\n",
    "\n",
    "Functions declared inside a [`struct`](/mojo/manual/structs) are called\n",
    "\"methods,\" but they have all the same qualities as \"functions\" described here.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `fn` functions\n",
    "\n",
    "The `fn` function has somewhat stricter rules than the `def` function.\n",
    "\n",
    "Here's an example of an `fn` function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn greet(name: String) -> String:\n",
    "    var greeting = \"Hello, \" + name + \"!\"\n",
    "    return greeting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As far as a function caller is concerned, `def` and `fn` functions are\n",
    "interchangeable. That is, there's nothing a `def` can do that an `fn` can't\n",
    "(and vice versa). The difference is that, compared to a `def` function, an `fn`\n",
    "function is more strict on the inside.\n",
    "\n",
    "Here's everything to know about `fn`:\n",
    "\n",
    "- Arguments must specify a type (except for the\n",
    "  `self` argument in [struct methods](/mojo/manual/structs#methods)).\n",
    "\n",
    "- Return values must specify a type, unless the function doesn't return a value.\n",
    "  \n",
    "  If you don't specify a return type, it defaults to `None` (meaning no return\n",
    "  value).\n",
    "\n",
    "- By default, arguments are received as an immutable reference (values are\n",
    "  read-only, using the `borrowed` [argument\n",
    "  convention](/mojo/manual/values/ownership#argument-conventions)).\n",
    "  \n",
    "  This prevents accidental mutations, and permits the use of non-copyable types\n",
    "  as arguments.\n",
    "  \n",
    "  If you want a local copy, you can simply assign the value to a local\n",
    "  variable. Or, you can get a mutable reference to the value by declaring the\n",
    "  `inout` [argument\n",
    "  convention](/mojo/manual/values/ownership#argument-conventions)).\n",
    "\n",
    "- [Variables](/mojo/manual/variables) must be declared using the `var`\n",
    "  keyword.\n",
    "\n",
    "- If the function raises an exception, it must be explicitly declared with the\n",
    "  `raises` keyword. (A `def` function does not need to declare exceptions.)\n",
    "\n",
    "By enforcing these type checks, using the `fn` function helps avoid a variety\n",
    "of runtime errors."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `def` functions\n",
    "\n",
    "Compared to an `fn` function, a `def` function has fewer restrictions.\n",
    "The `def` function works more like a Python\n",
    "`def` function. For example, this function works the same in Python and Mojo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greet(name):\n",
    "    greeting = \"Hello, \" + name + \"!\"\n",
    "    return greeting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In a Mojo `def` function, you have the option to specify the argument type and\n",
    "the return type. You can also declare variables with `var`, with or without\n",
    "explicit typing. So you can write a `def` function that looks almost exactly\n",
    "like the `fn` function shown earlier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greet(name: String) -> String:\n",
    "    var greeting = \"Hello, \" + name + \"!\"\n",
    "    return greeting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This way, the compiler ensures that `name` is a string, and the return type is a\n",
    "string.\n",
    "\n",
    "Here's everything to know about `def`:\n",
    "\n",
    "- Arguments don't require a declared type.\n",
    "\n",
    "  Undeclared arguments are actually passed as an\n",
    "  [`object`](/mojo/stdlib/builtin/object/object), which allows the\n",
    "  function to receive any type (Mojo infers the type at runtime).\n",
    "\n",
    "- Return types don't need to be declared, and also default to `object`. (If a \n",
    "  `def` function doesn't declare a return type of `None`, it's considered to\n",
    "  return an `object` by default.)\n",
    "\n",
    "- Arguments are mutable. Arguments default to using the using the `borrowed` \n",
    "  [argument convention](/mojo/manual/values/ownership#argument-conventions))\n",
    "  like an `fn` function, with a special addition: if the function mutates the\n",
    "  argument, it makes a mutable copy. \n",
    "\n",
    "  If an argument is an `object` type, it's received as a reference, following\n",
    "  [object reference\n",
    "  semantics](/mojo/manual/values/value-semantics#python-style-reference-semantics).\n",
    "  \n",
    "  If an argument is any other declared type, it's received as a value.\n",
    "\n",
    "- [Variables](/mojo/manual/variables) don't need to be declared using \n",
    "  `var`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The `object` type\n",
    "\n",
    "If you don't declare the type for an argument or return value in a `def`, it\n",
    "becomes an [`object`](/mojo/stdlib/builtin/object/object), which is unlike\n",
    "any other type in the standard library.\n",
    "\n",
    "The `object` type allows for dynamic typing because it can actually represent\n",
    "any type in the Mojo standard library, and the actual type is inferred at\n",
    "runtime. (Actually, there's still more to do before it can represent all Mojo\n",
    "types.) This is great for compatibility with Python and all of the flexibility\n",
    "that it provides with dynamic types. However, this lack of type enforcement can\n",
    "lead to runtime errors when a function receives or returns an unexpected type.\n",
    "\n",
    "For compatibility with Python, `object` values are passed using [object\n",
    "reference\n",
    "semantics](/mojo/manual/values/value-semantics#python-style-reference-semantics).\n",
    "As such, the `object` type is not compatible with the [argument\n",
    "conventions](/mojo/manual/values/ownership#argument-conventions) that\n",
    "enforce value semantics. So, be careful if using `object` values alongside other\n",
    "strongly-typed values—their behavior might be inconsistent because `object` is \n",
    "the only type in the standard library that does not conform to [full value\n",
    "semantics](/mojo/manual/values/value-semantics#full-value-semantics).\n",
    "\n",
    ":::note TODO\n",
    "\n",
    "The `object` type is still a work in progress. It doesn't support all of the\n",
    "possible underlying types, for example.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Function arguments\n",
    "\n",
    "As noted in the previous sections, there are a few differences between how `def`\n",
    "and `fn` functions treat arguments. But most of the time they are the same.\n",
    "\n",
    "As noted, there are some differences in _argument conventions_. \n",
    "Argument conventions are discussed in much more detail in the page on\n",
    "[Ownership](/mojo/manual/values/ownership#argument-conventions).\n",
    "\n",
    "The other difference is that `def` functions don't need to specify an argument's\n",
    "type. If no type is specified, the argument is passed as an \n",
    "[`object`](/mojo/stdlib/builtin/object/object).\n",
    "\n",
    "The remaining rules for arguments described in this section apply to both `def`\n",
    "and `fn` functions.\n",
    "\n",
    "### Optional arguments\n",
    "\n",
    "An optional argument is one that includes a default value, such as the `exp`\n",
    "argument here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn my_pow(base: Int, exp: Int = 2) -> Int:\n",
    "    return base ** exp\n",
    "\n",
    "fn use_defaults():\n",
    "    # Uses the default value for `exp`\n",
    "    var z = my_pow(3)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, you cannot define a default value for an argument that's declared as\n",
    "[`inout`](/mojo/manual/values/ownership.html#mutable-arguments-inout).\n",
    "\n",
    "Any optional arguments must appear after any required arguments. [Keyword-only\n",
    "arguments](#positional-only-and-keyword-only-arguments), discussed later, can\n",
    "also be either required or optional."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Keyword arguments\n",
    "\n",
    "You can also use keyword arguments when calling a function. Keyword arguments\n",
    "are specified using the format <code><var>argument_name</var> =\n",
    "<var>argument_value</var></code>. You can pass keyword arguments in any order:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn my_pow(base: Int, exp: Int = 2) -> Int:\n",
    "    return base ** exp\n",
    "\n",
    "fn use_keywords():\n",
    "    # Uses keyword argument names (with order reversed)\n",
    "    var z = my_pow(exp=3, base=2)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Variadic arguments\n",
    "\n",
    "Variadic arguments let a function accept a variable number of arguments. To\n",
    "define a function that takes a variadic argument, use the variadic argument\n",
    "syntax <code>*<var>argument_name</var></code>:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn sum(*values: Int) -> Int:\n",
    "  var sum: Int = 0\n",
    "  for value in values:\n",
    "    sum = sum + value\n",
    "  return sum"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The variadic argument `values` here is a placeholder that accepts any number of \n",
    "passed positional arguments.\n",
    "\n",
    "You can define zero or more arguments before the variadic argument. When calling\n",
    "the function, any remaining positional arguments are assigned to the variadic\n",
    "argument, so any arguments declared **after** the variadic argument can only be\n",
    "specified by keyword (see \n",
    "[Positional-only and keyword-only arguments](#positional-only-and-keyword-only-arguments)).\n",
    "\n",
    "Variadic arguments can be divided into two categories:\n",
    "\n",
    "- Homogeneous variadic arguments, where all of the passed arguments are the same\n",
    "  type—all `Int`, or all `String`, for example. \n",
    "- Heterogeneous variadic arguments, which can accept a set of different argument\n",
    "  types.\n",
    "\n",
    "The following sections describe how to work with homogeneous and heterogenous\n",
    "variadic arguments.\n",
    "\n",
    ":::note Variadic parameters\n",
    "\n",
    "Mojo [parameters](/mojo/manual/parameters/) are distinct from arguments\n",
    "(parameters are used for compile-time metaprogramming). Variadic parameters\n",
    "are supported, but with some limitations—for details see \n",
    "[variadic parameters](/mojo/manual/parameters/#variadic-parameters).\n",
    "\n",
    ":::\n",
    "\n",
    "\n",
    "#### Homogeneous variadic arguments\n",
    "\n",
    "When defining a homogeneous variadic argument, use \n",
    "<code>*<var>argument_name</var>: <var>argument_type</var></code>:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greet(*names: String):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Inside the function body, the variadic argument is available as an iterable list\n",
    "for ease of use. Currently there are some differences in handling the list \n",
    "depending on whether the arguments are register-passable types (such as `Int`)\n",
    "or memory-only types (such as `String`). TODO: We hope to remove these\n",
    "differences in the future.\n",
    "\n",
    "Register-passable types, such as `Int`, are available as a \n",
    "[`VariadicList`](/mojo/stdlib/builtin/builtin_list/VariadicList) type. As\n",
    "shown in the previous example, you can iterate over the values using a `for..in`\n",
    "loop."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn sum(*values: Int) -> Int:\n",
    "  var sum: Int = 0\n",
    "  for value in values:\n",
    "    sum = sum+value\n",
    "  return sum"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Memory-only types, such as `String`, are available as a \n",
    "[`VariadicListMem`](/mojo/stdlib/builtin/builtin_list/VariadicListMem).\n",
    "Iterating over this list directly with a `for..in` loop currently produces a\n",
    "[`Reference`](/mojo/stdlib/memory/unsafe/reference) for each value instead\n",
    "of the value itself. You must add an empty subscript operator `[]` to\n",
    "dereference the reference and retrieve the value:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_worldly(inout *strs: String):\n",
    "    # Requires extra [] to dereference the reference for now.\n",
    "    for i in strs:\n",
    "        i[] += \" world\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Alternately, subscripting into a `VariadicListMem` returns the argument value,\n",
    "and doesn't require any dereferencing:\n",
    "\n",
    "  ```mojo\n",
    "  fn make_worldly(inout *strs: String):\n",
    "      # This \"just works\" as you'd expect!\n",
    "      for i in range(len(strs)):\n",
    "          strs[i] += \" world\"\n",
    "  ```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Heterogeneous variadic arguments\n",
    "\n",
    "Implementing heterogeneous variadic arguments is somewhat more complicated than\n",
    "homogeneous variadic arguments. Writing generic code to handle multiple argument\n",
    "types requires [traits](/mojo/manual/traits) and \n",
    "[parameters](/mojo/manual/parameters/). So the syntax may look a little\n",
    "unfamiliar if you haven't worked with those features. The signature for a\n",
    "function with a heterogeneous variadic argument looks like this:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```mojo\n",
    "def count_many_things[*ArgTypes: Intable](*args: *ArgTypes):\n",
    "    ...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The parameter list, `[*ArgTypes: Intable]` specifies that the function takes an\n",
    "`ArgTypes` parameter, which is a list of types, all of which conform to the \n",
    "[`Intable`](/mojo/stdlib/builtin/int/Intable) trait. The argument list, \n",
    "`(*args: *ArgTypes)` has the familiar `*args` for the variadic argument, but \n",
    "instead of a single type, its type is defined as _list_ of types, `*ArgTypes`.\n",
    "\n",
    "This means that each argument in `args` has a corresponding type in `ArgTypes`, \n",
    "so <code>args[<var>n</var>]</code> is of type \n",
    "<code>ArgTypes[<var>n</var>]</code>.\n",
    "\n",
    "Inside the function, `args` is available as a\n",
    "[`VariadicPack`](/mojo/stdlib/builtin/builtin_list/VariadicPack). The easiest\n",
    "way to work with the arguments is to use the `each()` method to iterate through\n",
    "the `VariadicPack`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "28\n"
     ]
    }
   ],
   "source": [
    "fn count_many_things[*ArgTypes: Intable](*args: *ArgTypes) -> Int:\n",
    "    var total = 0\n",
    "\n",
    "    @parameter\n",
    "    fn add[Type: Intable](value: Type):\n",
    "        total += int(value)\n",
    "\n",
    "    args.each[add]()\n",
    "    return total\n",
    "\n",
    "print(count_many_things(5, 11.7, 12))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the example above, the `add()` function is called for each argument in turn,\n",
    "with the appropriate `value` and `Type` values. For instance, `add()` is first\n",
    "called with `value=5` and `Type=Int`, then with `value=11.7` and `Type=Float64`.\n",
    "\n",
    "Also, note that when calling `count_many_things()`, you don't actually pass in\n",
    "a list of argument types. You only need to pass in the arguments, and Mojo\n",
    "generates the `ArgTypes` list itself.\n",
    "\n",
    "As a small optimization, if your function is likely to be called with a single\n",
    "argument frequently, you can define your function with a single argument\n",
    "followed by a variadic argument. This lets the simple case bypass populating and\n",
    "iterating through the `VariadicPack`.\n",
    "\n",
    "For example, given a `print_string()` function that prints a single string, you\n",
    "could re-implement the variadic `print()` function with code like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bob\n"
     ]
    }
   ],
   "source": [
    "fn print_string(s: String):\n",
    "    print(s, end=\"\")\n",
    "\n",
    "fn print_many[T: Stringable, *Ts: Stringable](first: T, *rest: *Ts):\n",
    "    print_string(str(first))\n",
    "\n",
    "    @parameter\n",
    "    fn print_elt[T: Stringable](a: T):\n",
    "        print_string(\" \")\n",
    "        print_string(a)\n",
    "    rest.each[print_elt]()\n",
    "print_many(\"Bob\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you call `print_many()` with a single argument, it calls `print_string()`\n",
    "directly. The `VariadicPack` is empty, so `each()` returns immediately without\n",
    "calling the `print_elt()` function."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Variadic keyword arguments\n",
    "\n",
    "Mojo functions also support variadic keyword arguments (`**kwargs`). Variadic\n",
    "keyword arguments allow the user to pass an arbitrary number of keyword\n",
    "arguments. To define a function that takes a variadic keyword argument, use the\n",
    "variadic keyword argument syntax <code>**<var>kw_argument_name</var></code>:\n",
    "\n",
    "  ```mojo\n",
    "  fn print_nicely(**kwargs: Int) raises:\n",
    "    for key in kwargs.keys():\n",
    "        print(key[], \"=\", kwargs[key[]])\n",
    "\n",
    "   # prints:\n",
    "   # `a = 7`\n",
    "   # `y = 8`\n",
    "  print_nicely(a=7, y=8)\n",
    "  ```\n",
    "\n",
    "  In this example, the argument name `kwargs` is a placeholder that accepts any\n",
    "  number of keyword arguments. Inside the body of the function, you can access\n",
    "  the arguments as a dictionary of keywords and argument values (specifically,\n",
    "  an instance of\n",
    "  [`OwnedKwargsDict`](/mojo/stdlib/collections/dict/OwnedKwargsDict)).\n",
    "  \n",
    "  \n",
    "  There are currently a few limitations:\n",
    "\n",
    "  - Variadic keyword arguments are always implicitly treated as if they\n",
    "    were declared with the `owned` [argument \n",
    "    convention](/mojo/manual/values/ownership.html#argument-conventions), and\n",
    "    can't be declared otherwise:\n",
    "\n",
    "    ```mojo\n",
    "    # Not supported yet.\n",
    "    fn borrowed_var_kwargs(borrowed **kwargs: Int): ...\n",
    "    ```\n",
    "\n",
    "  - All the variadic keyword arguments must have the same type, and this\n",
    "    determines the type of the argument dictionary. For example, if the argument\n",
    "    is `**kwargs: Float64` then the argument dictionary will be a \n",
    "    `OwnedKwargsDict[Float64]`.\n",
    "\n",
    "  - The argument type must conform to the \n",
    "    [`CollectionElement`](/mojo/stdlib/builtin/value/CollectionElement) trait.\n",
    "    That is, the type must be both [`Movable`](/mojo/stdlib/builtin/value/Movable)\n",
    "    and [`Copyable`](/mojo/stdlib/builtin/value/Copyable).\n",
    "\n",
    "  - Dictionary unpacking is not supported yet:\n",
    "\n",
    "    ```mojo\n",
    "    fn takes_dict(d: Dict[String, Int]):\n",
    "      print_nicely(**d)  # Not supported yet.\n",
    "    ```\n",
    "\n",
    "  - Variadic keyword _parameters_ are not supported yet:\n",
    "\n",
    "    ```mojo\n",
    "    # Not supported yet.\n",
    "    fn var_kwparams[**kwparams: Int](): ...\n",
    "    ```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Positional-only and keyword-only arguments\n",
    "\n",
    "When defining a function, you can restrict some arguments so that they can only\n",
    "be passed as positional arguments, or they can only be passed as keyword \n",
    "arguments.\n",
    "\n",
    "To define positional-only arguments, add a slash character (`/`) to the\n",
    "argument list. Any arguments before the `/` are positional-only: they can't be\n",
    "passed as keyword arguments. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn min(a: Int, b: Int, /) -> Int:\n",
    "    return a if a < b else b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This `min()` function can be called with `min(1, 2)` but can't be called using\n",
    "keywords, like `min(a=1, b=2)`.\n",
    "\n",
    "There are several reasons you might want to write a function with\n",
    "positional-only arguments:\n",
    "\n",
    "- The argument names aren't meaningful for the the caller.\n",
    "- You want the freedom to change the argument names later on without breaking\n",
    "  backward compatibility.\n",
    "\n",
    "For example, in the `min()` function, the argument names don't add any real\n",
    "information, and there's no reason to specify arguments by keyword. \n",
    "\n",
    "For more information on positional-only arguments, see [PEP 570 – Python\n",
    "Positional-Only Parameters](https://peps.python.org/pep-0570/).\n",
    "\n",
    "Keyword-only arguments are the inverse of positional-only arguments: they can\n",
    "only be specified by keyword. If a function accepts variadic arguments, any \n",
    "arguments defined _after_ the variadic arguments are treated as keyword-only.\n",
    "For example:\n",
    "\n",
    "```mojo\n",
    "fn sort(*values: Float64, ascending: Bool = True): ...\n",
    "```\n",
    "\n",
    "In this example, the user can pass any number of `Float64` values, optionally\n",
    "followed by the keyword `ascending` argument:\n",
    "\n",
    "```mojo\n",
    "var a = sort(1.1, 6.5, 4.3, ascending=False)\n",
    "```\n",
    "\n",
    "If the function doesn't accept variadic arguments, you can add a single star\n",
    "(`*`) to the argument list to separate the keyword-only arguments:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn kw_only_args(a1: Int, a2: Int, *, double: Bool) -> Int:\n",
    "    var product = a1 * a2\n",
    "    if double:\n",
    "        return product * 2\n",
    "    else:\n",
    "        return product"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Keyword-only arguments often have default values, but this is not required. If a\n",
    "keyword-only argument doesn't have a default value, it is a _required \n",
    "keyword-only argument_. It must be specified, and it must be specified by \n",
    "keyword. \n",
    "\n",
    "Any required keyword-only arguments must appear in the signature before\n",
    "any optional keyword-only arguments. That is, arguments appear in the following\n",
    "sequence a function signature:\n",
    "\n",
    "* Required positional arguments.\n",
    "* Optional positional arguments.\n",
    "* Variadic arguments.\n",
    "* Required keyword-only arguments.\n",
    "* Optional keyword-only arguments.\n",
    "* Variadic keyword arguments.\n",
    "\n",
    "For more information on keyword-only arguments, see [PEP 3102 – Keyword-Only\n",
    "Arguments](https://peps.python.org/pep-3102/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Overloaded functions\n",
    "\n",
    "If a `def` function does not specify argument types, then it can accept any\n",
    "data type and decide how to handle each type internally. This is nice when you\n",
    "want expressive APIs that just work by accepting arbitrary inputs, so there's\n",
    "usually no need to write function overloads for a `def` function.\n",
    "\n",
    "On the other hand, all `fn` functions must specify argument types, so if you\n",
    "want a function to work with different data types, you need to implement\n",
    "separate versions of the function that each specify different argument types.\n",
    "This is called \"overloading\" a function.\n",
    "\n",
    "For example, here's an overloaded `add()` function that can accept either\n",
    "`Int` or `String` types:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn add(x: Int, y: Int) -> Int:\n",
    "    return x + y\n",
    "\n",
    "fn add(x: String, y: String) -> String:\n",
    "    return x + y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you pass anything other than `Int` or `String` to the `add()` function,\n",
    "you'll get a compiler error. That is, unless `Int` or `String` can implicitly\n",
    "cast the type into their own type. For example, `String` includes an overloaded\n",
    "version of its constructor (`__init__()`) that accepts a `StringLiteral` value.\n",
    "Thus, you can also pass a `StringLiteral` to a function that expects a `String`.\n",
    "\n",
    "When resolving an overloaded function call, the Mojo compiler tries each\n",
    "candidate function and uses the one that works (if only one version works), or\n",
    "it picks the closest match (if it can determine a close match), or it reports\n",
    "that the call is ambiguous (if it can’t figure out which one to pick).\n",
    "\n",
    "If the compiler can't figure out which function to use, you can resolve the\n",
    "ambiguity by explicitly casting your value to a supported argument type. For\n",
    "example, in the following code, we want to call the overloaded `foo()`\n",
    "function, but both implementations accept an argument that supports [implicit\n",
    "conversion](/mojo/manual/variables.html#implicit-type-conversion) from\n",
    "`StringLiteral`. So, the call to `foo(string)` is ambiguous and creates a\n",
    "compiler error. We can fix it by casting the value to the type we really want:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "@value\n",
    "struct MyString:\n",
    "    fn __init__(inout self, string: StringLiteral):\n",
    "        pass\n",
    "\n",
    "fn foo(name: String):\n",
    "    print(\"String\")\n",
    "\n",
    "fn foo(name: MyString):\n",
    "    print(\"MyString\")\n",
    "\n",
    "fn call_foo():\n",
    "    alias string: StringLiteral = \"Hello\"\n",
    "    # foo(string) # This call is ambiguous because two `foo` functions match it\n",
    "    foo(MyString(string))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "When resolving an overloaded function, Mojo does not consider the return type\n",
    "or other contextual information at the call site—only the argument types affect\n",
    "which function is selected.\n",
    "\n",
    "Overloading also works with combinations of both `fn` and `def` functions.\n",
    "For example, you could define multiple `fn` function overloads and then one\n",
    "or more `def` versions that don't specify all argument types, as a fallback.\n",
    "\n",
    ":::note\n",
    "\n",
    "Although we haven't discussed\n",
    "[parameters](/mojo/manual/parameters/) yet (they're\n",
    "different from function arguments, and used for compile-time metaprogramming),\n",
    "you can also overload functions based on parameter types.\n",
    "\n",
    ":::"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Mojo",
   "language": "mojo",
   "name": "mojo-jupyter-kernel"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "mojo"
   },
   "file_extension": ".mojo",
   "mimetype": "text/x-mojo",
   "name": "mojo"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
